package it.uniroma2.sd.db;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Hashtable;
import java.util.Vector;

public class DBsManager
{
    private Hashtable<String, DB> dbs;
    private Hashtable<String, String> serialized_dbs;

    public DBsManager()
    {
	this.dbs = new Hashtable<String, DB>();
	this.serialized_dbs = new Hashtable<String, String>();

    }

    /* public static DBController createDBController()
     {
    //TODO make constructor private and put other things here..
    return  new DBsManager();
     }
     */

    /**
     * Create a database with a specified identification name.
     * 
     * @param id The database identification name.
     * @return TRUE if the DB does not exist yet , FALSE otherwise
     */
    // FIXME documentation
    public boolean createDB(String id)
    {
	DB newdb = new DB(id);
	return (this.dbs.put(newdb.getId(), newdb) == null);
    }

    public boolean serializeDB(String DBid) throws IOException
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return false;
	FileOutputStream fos = new FileOutputStream(DBid + ".ser");
	ObjectOutputStream oos = new ObjectOutputStream(fos);
	oos.writeObject(chosendb);
	oos.close();
	this.serialized_dbs.put(DBid, DBid + ".ser"); // insert in file
	this.dbs.remove(DBid); // remove from RAM memory TODO FIXME in realtà qui imposterei a NULL (facendo relativi controlli su altre strutture se NUL è supportato) in modo da non far inserire nuovi DB con quello stesso ID
	return true;

    }

    public DB deserializeDB(String DBid) throws IOException, ClassNotFoundException
    {

	DB chosendb;
	/*if ((chosendb = this.dbs.get(DBid)) == null)
	    return null;
	    */
	FileInputStream fos = new FileInputStream(DBid + ".ser");
	ObjectInputStream ois = new ObjectInputStream(fos);

	DB retDB = (DB) ois.readObject();
	if (retDB != null)
	{
	    this.dbs.put(DBid, retDB);
	    return retDB;
	}
	return null;
    }

    public boolean createTableInDB(String DBid, String tablename)
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return false;
	return chosendb.createTable(tablename);
    }

    public boolean deleteDB(String id)
    {
	return (this.dbs.remove(id) != null);
    }

    public boolean deleteTable(String DBid, String tablename)
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return false;
	return chosendb.deleteTable(tablename);
    }

    public boolean putInTable(String DBid, String tablename, String rowkey, IColumn column)
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return false;

	return chosendb.putInTable(tablename, rowkey, column);
    }

    public boolean putInTable(String DBid, String tablename, String rowkey, IColumn... columns)
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return false;

	return chosendb.putInTable(tablename, rowkey, columns);
    }

    public IColumn getColumnFromTable(String DBid, String tablename, String rowkey, String columnkey)
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return null;

	return chosendb.getColumnFromTable(tablename, rowkey, columnkey);
    }

    public Vector<IColumn> getAllColumnsFromTable(String DBid, String tablename, String rowkey)
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return null;

	return chosendb.getAllColumnsFromTable(tablename, rowkey);
    }

    public boolean deleteColumnFromTable(String DBid, String tablename, String rowkey, String columnkey)
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return false;

	return chosendb.deleteColumnFromTable(tablename, rowkey, columnkey);
    }

    public int deleteColumnsFromTable(String tablename, String rowkey, String... columnkey)
    {
	// TODO Auto-generated method stub
	// FIXME decidere se permettere la cancellazione di piu' colonne insieme.
	System.out.println("----FIXME-----");
	return 0;
    }

    public boolean deleteRowFromTable(String DBid, String tablename, String rowkey)
    // FIXME ritorna null in 2 casi: NOtable, NOrow. separare o usare exception
    {
	DB chosendb;
	if ((chosendb = this.dbs.get(DBid)) == null)
	    return false;

	return chosendb.deleteRowFromTable(tablename, rowkey);
    }

}
